package logicaDePredicados;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import exceptions.UnDecidibleValueException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;

public class LogicPredicate <T> extends PredicateLogic{
	private HashMap <T,Boolean> valueMap;
	
	/**
	 * predicate function constructor
	 * @param name
	 */
	public LogicPredicate(String name) {
		super();
		this.setName(name);
		valueMap = new HashMap<T, Boolean> ();
		
	}
	/**
	 * Returns the value corresponding to the domain of the function. Throws exception when
	 * an invalid value is used.
	 * @param object
	 * @return
	 * @throws UnDecidibleValueException
	 */
	public Boolean getTruthValue (Object object) throws UnDecidibleValueException{
		Boolean returnValue = valueMap.get(object);
		if (returnValue==null)
			throw new UnDecidibleValueException(object.toString()+" not found in predicate "+getName());
		return returnValue;
	}
	/**
	 * Adds a valid constant value and its corresponding boolean value to 
	 * the domain of this predicate function
	 * @param value
	 * @param truthValue
	 */
	public void addTruthValue (T value, boolean truthValue){
		valueMap.put(value,new Boolean(truthValue));
	}

        @Override
        public String toString(){
            return getName()+"(x)";
        }
	public String getFullListing (){
		StringBuffer returnValue=new StringBuffer();
		Iterator<T> i = valueMap.keySet().iterator();
		while (i.hasNext()){
			T keyValue = i.next();
			Boolean value=valueMap.get(keyValue);
			returnValue.append(this.getName()+"("+keyValue+")"+"\t"+value+"\n");
			
		}
			
		
		return returnValue.toString();
	}
	
	@Override
	public boolean equals (Object o){
		/**
		 * if the objects are indeed the same class then compare their names
		 */
		if (o.getClass()==this.getClass()){
			return this.getName().equalsIgnoreCase(((LogicPredicate<?>)o).getName());
		}
		return false;
		
	}
	/**
	 * @return the valueList
	 */
	public Collection<PredicateConstant<T>> getValueList() {
		ArrayList<PredicateConstant<T>> valueList = new ArrayList<PredicateConstant<T>>();
		for (T value : valueMap.keySet()) {
			valueList.add(new PredicateConstant<T>(value));
			
		}
		return valueList;
	}
        /**
         * Get the values and keys of the predicate as a matrix of Object.
         * Used for GUI purposes
         * @return
         */
        public Object [][] getDataMatrix (){

           Set<Entry <T,Boolean>> entrySet = valueMap.entrySet();
           Object[][] matrix = new Object[entrySet.size()][entrySet.size()];
           int i=0;
           for (Entry<T, Boolean> entry : entrySet) {
                matrix[i][0]= entry.getKey();
                matrix[i][1]=entry.getValue();
                i++;
           }
            return matrix;

        }
        /**
         * Returns a list containing the keys. Use for GUI purposes ONLY
         * @return
         */
        public List<T> getKeyList (){

            List <T> returnList = new LinkedList<T>();
            returnList.addAll(valueMap.keySet());
            return returnList;
        }
        public void removeKey (T key){

            valueMap.remove(key);
        }
        
}
